package com.ecoolex.chinadutyfree.retailer.core.manager;

import java.time.Instant;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ecoolex.chinadutyfree.retailer.core.dao.FreightTemplateDAO;
import com.ecoolex.chinadutyfree.retailer.entity.FreightTemplate;
import com.ecoolex.chinadutyfree.retailer.entity.FreightTemplate.Column;
import com.ecoolex.chinadutyfree.retailer.entity.FreightTemplateExample;
import com.ecoolex.chinadutyfree.retailer.enums.FreightTemplatePricingModel;
import com.ecoolex.chinadutyfree.retailer.pojo.EditFreightTemplateChargingDTO;
import com.ecoolex.chinadutyfree.retailer.pojo.QueryFreightTemplateDTO;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.google.common.collect.Lists;


@Service
public class FreightTemplateManager {

	@Autowired
	private FreightTemplateDAO dao;

	@Autowired
	private FreightTemplateChargingManager chargingManager;

	@Autowired
	private DirectMailGoodsManager directMailGoodsManager;

	private void verify(FreightTemplate record, List<EditFreightTemplateChargingDTO> chargingList) {
		BizAssert.isTrue(Check.notNullOrTrimEmpty(record.getName()), ResultCode.VERIFY.build(10), "名称为空");
		FreightTemplatePricingModel model = FreightTemplatePricingModel.NUMBER.realOf(record.getPricingModel());
		BizAssert.isTrue(Check.notNull(model), ResultCode.VERIFY.build(11), "计算模式不存在");
		BizAssert.isTrue(Check.notNullOrTrimEmpty(record.getCurrencyType()), ResultCode.VERIFY.build(12), "币种为空");

		// 计费
		BizAssert.isTrue(Check.notNullOrEmpty(chargingList), ResultCode.VERIFY.build(20), "至少需要一种计费规则");

		List<Integer> allRegionList
			= chargingList.stream().map(EditFreightTemplateChargingDTO::getRegionList).reduce(Lists.newArrayList(),
				(result, item) -> {
					result.addAll(item);
					return result;
				});
		BizAssert.isTrue(allRegionList.size() == allRegionList.stream().distinct().count(),
			ResultCode.VERIFY.build(13),
			"在{}种计费中存在配置相同的区域",
			chargingList.size());
	}

	@Transactional
	public FreightTemplate add(FreightTemplate record, List<EditFreightTemplateChargingDTO> chargingList, String createUser) {
		verify(record, chargingList);

		record.setDeleted(FreightTemplate.NOT_DELETED);
		record.setCreateUser(createUser);
		record.setCreateTime(Date.from(Instant.now()));
		record.setUpdateUser(createUser);
		record.setUpdateTime(Date.from(Instant.now()));
		dao.insert(record);

		chargingManager.update(record, chargingList, createUser);

		return record;
	}

	@Transactional
	public FreightTemplate edit(FreightTemplate record, List<EditFreightTemplateChargingDTO> chargingList, String updateUser) {
		verify(record, chargingList);

		record.setUpdateUser(updateUser);
		record.setUpdateTime(Date.from(Instant.now()));
		dao.updateByPrimaryKeySelective(record,
			Column.excludes(Column.pricingModel,
				Column.currencyType,
				Column.deleted,
				Column.createUser,
				Column.createTime));

		chargingManager.update(record, chargingList, updateUser);

		return record;
	}

	@Transactional
	public void delete(FreightTemplate record, String updateUser) {
		// 检查是否有引用
		long directMailGoods = directMailGoodsManager.countByFreightTemplateId(record.getFreightTemplateId());
		BizAssert.isTrue(Check.isLessThan(directMailGoods, 1L),
			ResultCode.BIZ.build(1),
			"有{}个直邮商品使用了该运费模板,无法删除",
			directMailGoods);

		record.setDeleted(FreightTemplate.IS_DELETED);
		record.setUpdateUser(updateUser);
		record.setUpdateTime(Date.from(Instant.now()));
		dao.updateByPrimaryKeySelective(record, Column.deleted, Column.updateUser, Column.updateTime);

		chargingManager.deleteByFreightTemplate(record, updateUser);
	}

	public FreightTemplate getById(Integer freightTemplateId) {
		return dao.selectByPrimaryKeyWithLogicalDelete(freightTemplateId, FreightTemplate.NOT_DELETED);
	}

	public Pagination<FreightTemplate> query(QueryFreightTemplateDTO query, Sorting[] sorts, Page page) {
		FreightTemplateExample example = new FreightTemplateExample();
		FreightTemplateExample.Criteria criteria = example.createCriteria();

		if (Check.notNullOrTrimEmpty(query.getName())) {
			criteria.andNameLike('%' + query.getName()
				+ '%');
		}
		if (Check.notNull(query.getPricingModel())) {
			criteria.andPricingModelEqualTo(query.getPricingModel());
		}
		if (Check.notNullOrTrimEmpty(query.getCurrencyType())) {
			criteria.andCurrencyTypeEqualTo(query.getCurrencyType());
		}

		criteria.andDeletedEqualTo(FreightTemplate.NOT_DELETED);
		example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
		example.setOffset(page.getFirstIndex());
		example.setRows(page.getPageSize());

		return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
	}
}